package botsim;

import com.ardor3d.extension.model.collada.jdom.ColladaImporter;
import com.ardor3d.framework.DisplaySettings;
import com.ardor3d.framework.NativeCanvas;
import com.ardor3d.framework.Scene;
import com.ardor3d.framework.jogl.JoglCanvas;
import com.ardor3d.framework.jogl.JoglCanvasRenderer;
import com.ardor3d.framework.lwjgl.LwjglCanvas;
import com.ardor3d.framework.lwjgl.LwjglCanvasRenderer;
import com.ardor3d.input.PhysicalLayer;
import com.ardor3d.input.control.FirstPersonControl;
import com.ardor3d.input.logical.LogicalLayer;
import com.ardor3d.input.lwjgl.LwjglKeyboardWrapper;
import com.ardor3d.input.lwjgl.LwjglMouseWrapper;
import com.ardor3d.intersection.PickResults;
import com.ardor3d.light.PointLight;
import com.ardor3d.math.ColorRGBA;
import com.ardor3d.math.Ray3;
import com.ardor3d.math.Vector3;
import com.ardor3d.renderer.Renderer;
import com.ardor3d.renderer.state.LightState;
import com.ardor3d.renderer.state.ZBufferState;
import com.ardor3d.scenegraph.Node;
import com.ardor3d.util.Timer;
import com.ardor3d.util.resource.URLResourceSource;
import java.io.File;
import java.net.MalformedURLException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * In this example i will show tou how to create a box in your scene (it is based on previeus example)
 * @author Kalvis Freimanis
 *
 */
public class ObjectInSceneExample implements Scene {

    /**
     * Define some static data so that we can chose what rendering do user LWJGL of JOGL
     * default is LWJGL
     */
    public final static int LWJGL_RENDERER = 0;
    public final static int JOGL_RENDERER = 1;
    /**
     * Root node base of our scene
     * This Node holds all other scene nodes and other stuff that needs do be renderd
     */
    private final Node _rootNode;
    /**
     * This is our window where in our scene is displayed
     */
    private final NativeCanvas _canvas;
    /**
     * Timer to keep track how much time has passed between frames
     */
    private final Timer _timer;

    private LogicalLayer _logicalLayer;

    /**
     * boolean that says when to exit
     */
    private boolean _exit = false;

    /**
     * Nothing special simple constructor of our example
     * @param renderer indicates what renderer to use LWJGL of JOGL
     */
    public ObjectInSceneExample(int renderer) {

        /**
         *  Display settings width height and full screen  or not
         */
        final DisplaySettings settings = new DisplaySettings(800, 600, 24, 0,
                0, 8, 0, 0, false, false);

        /**
         * Create Renderer and our Window
         */
        switch (renderer) {
            case JOGL_RENDERER:
                /**
                 * Creates JOGL renderer to who we passe our scene (Thats way we implemented Scene)
                 */
                final JoglCanvasRenderer joglRenderer = new JoglCanvasRenderer(this);

                /**
                 * Create JOGL Window passing renderer and settings for size and so
                 */
                _canvas = new JoglCanvas(joglRenderer, settings);
                break;
            case LWJGL_RENDERER:
            default:
                /**
                 * Creates LWJGL renderer to who we passe our scene (Thats way we implemented Scene)
                 */
                final LwjglCanvasRenderer lwjglRenderer = new LwjglCanvasRenderer(this);

                /**
                 * Create LWJGL Window passing renderer and settings for size and so
                 */
                _canvas = new LwjglCanvas(lwjglRenderer, settings);
                break;
        }

        /**
         * Initilze out window
         */
        _canvas.init();

        /**
         * Set title to our window
         */
        _canvas.setTitle("Create Scene Example");

        /**
         * Creating instance of timer
         */
        _timer = new Timer();

        /**
         * Creating our root node;
         */
        _rootNode = new Node();

    }

    /**
     * This is functions where Actual rendering of our scene happens
     */
    @Override
    public boolean renderUnto(Renderer renderer) {
        // see if we are closing windows
        if (!_canvas.isClosing()) {

            // Draw the root node and all its children.
            renderer.draw(_rootNode);

            return true;
        }
        return false;
    }

    /**
     * this is for scene building stuff adding objects to scene and so
     */
    public void initScene() {
        Node car = null;
        try {
            car = new ColladaImporter().readColladaFile(new URLResourceSource(new File("./wallSection.dae").toURI().toURL())).getScene();
        } catch (MalformedURLException ex) {
            Logger.getLogger(ObjectInSceneExample.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        // Move camera back so that wee can see it
        // More information about camera in following tutorials
        _canvas.getCanvasRenderer().getCamera().setLocation(new Vector3(0, 10, 0));
        
        _canvas.getCanvasRenderer().getCamera().setDirection(new Vector3(0, -1, 0));
        _canvas.getCanvasRenderer().getCamera().setUp(new Vector3(0, 0, 1));
        _canvas.getCanvasRenderer().getCamera().setLeft(new Vector3(-1, 0, 0));


        // ---- LIGHTS
        /** Set up a basic, default light. */
        final PointLight light = new PointLight();
        light.setDiffuse(new ColorRGBA(0.75f, 0.75f, 0.75f, 0.75f));
        light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
        light.setLocation(new Vector3(100, 100, 100));
        light.setEnabled(true);

        /** Attach the light to a lightState and the lightState to rootNode. */
        LightState _lightState = new LightState();
        _lightState.setEnabled(true);
        _lightState.attach(light);
        _rootNode.setRenderState(_lightState);

        // Layer setup
        PhysicalLayer physicalLayer = new PhysicalLayer(new LwjglKeyboardWrapper(), new LwjglMouseWrapper(), (LwjglCanvas)_canvas);
        _logicalLayer = new LogicalLayer();
        _logicalLayer.registerInput(_canvas, physicalLayer);

        FirstPersonControl control = new FirstPersonControl(_canvas.getCanvasRenderer().getCamera().getUp());
        control.setMouseRotateSpeed(0.002);
        control.setMoveSpeed(10.0);
        control.setupKeyboardTriggers(_logicalLayer);
        control.setupMouseTriggers(_logicalLayer, true, null);

        /**
         * Create a ZBuffer to display pixels closest to the camera above farther ones.
         *
         *   More information about RenderStates in following tutorials
         *    This makes shore that box is drawn in right order
         * remove this code and see what what is dose
         */
        final ZBufferState buf = new ZBufferState();
        buf.setEnabled(true);
        buf.setFunction(ZBufferState.TestFunction.LessThanOrEqualTo);
        _rootNode.setRenderState(buf);

        /**
         * Attach box to our rootNode so that it is rendered and we can see it
         */
        _rootNode.attachChild(car);

    }

    /**
     * This is place where we update our scene
     */
    public void update() {
        // see if we are closing windows
        if (_canvas.isClosing()) {
            _exit = true;
            return;
        }

        /**
         * Update timer so that time passed between frames can be calculated
         */
        _timer.update();

        // Update controllers/render states/transforms/bounds for rootNode.
        _logicalLayer.checkTriggers(_timer.getTimePerFrame());
        _rootNode.updateGeometricState(_timer.getTimePerFrame(), true);
        
    }

    /**
     * Main loop this loop runs as long as our program
     */
    public void mainLoop() {
        // call init scene to build our scene
        initScene();

        // Render and update our scene.
        while (!_exit) {
            // update scene
            update();
            // render our scene
            _canvas.draw(null);
            // We are nice so we let other Thread play too (You must always be nice, or else)
            Thread.yield();
        }

        // destroy our window;
        _canvas.close();

        //exit application
    }

    @Override
    public PickResults doPick(Ray3 pickRay) {
        // TODO Auto-generated method stub
        return null;
    }

    public static void main(String[] args) {
        // Create our example this LWJGL renderer
        ObjectInSceneExample exp = new ObjectInSceneExample(LWJGL_RENDERER);
        //Start main loop
        exp.mainLoop();
    }
}

